package Market;


import java.util.*;

import edu.iastate.jrelm.rl.SimpleStatelessLearner;
import sim.engine.*;


public class Market extends SimState{
	
	private static final long serialVersionUID = 6628525522939315274L;
												
												/** Priorities counter to fire agents in a chosen order */
	  private int count = 0;
												/** Number of Branches*/
	  public int N=5;
	 
	  public Hashtable<String, Double> branchListONE = new Hashtable<String, Double>() ;
	  public Hashtable<String, Double> branchListTWO = new Hashtable<String, Double>() ;
	  public Hashtable<String, Double> branchListTHREE = new Hashtable<String, Double>() ;
	  public Hashtable<String, Double> branchListFOUR = new Hashtable<String, Double>() ;
	  public Hashtable<String, Double> branchListFIVE = new Hashtable<String, Double>() ;
	  
	  
	 // public Hashtable<String, Hashtable<String, Double>> branchList = new Hashtable<String, Hashtable<String, Double>>() ;
	  public Hashtable<String, Double> nodeData = new Hashtable<String, Double>() ;
	  											/** Number of Nodes*/
	  public int K=5;
	  											/** Boolean used to separate GenCo's methods execution  */
//	  boolean Switch;
	  											/** Number of days of market operation */
	  private int TotalDays = 10;
	  
	  
// GenCo												
												/** Number of GenCos */
	  public int I=5;
	  											/** GenCos location at node  */
	  private int[] GenCoAtNode;
	  											/** GenCos list */
	  private ArrayList GenCoList;
	  											/** Action domains list */
	  private ArrayList ADList;
	  											/** Learners list */
	  private ArrayList<SimpleStatelessLearner<?>> LearnerList;
	  											/** GenCo's Data: {Gen ID, at Node, FCost, aT, bT, CapTL, CapTU, Initial Money in pounds} */
	  private double[][] GenCoData;
	  											/** Learning Data: {initial propensity, Cooling, Recency, Experimentation, M1, M2, M3, RIMaxL, RIMaxU, RIMinC, SlopeStart, Reward Selection} */
	  private double[][] LearningData;
	  											/** True Supply Offer: {aT,bT,CapTL,CapTU} */
	  private double[][] TSupplyOffer;
	  											/** Reported Supply Offer: {aR,bR,CapRL,CapRU} */
	  private double[][] RSupplyOffer;
	  											/** Hourly power production quantity by GenCos */
	  public Hashtable<String, Double> lmpNode1 = new Hashtable<String, Double>() ;
	  public Hashtable<String, Double> lmpNode2 = new Hashtable<String, Double>() ;
	  public Hashtable<String, Double> lmpNode3 = new Hashtable<String, Double>() ;
	  public Hashtable<String, Double> lmpNode4 = new Hashtable<String, Double>() ;
	  public Hashtable<String, Double> lmpNode5 = new Hashtable<String, Double>() ;
	  
	  //  public double[][] Commitment;
	  											/** GenCo's accumulative money holding, money (new) = money(previous) + dailyProfit(new) */
	  private double[] GenCoMoney;
	  
	  SimpleStatelessLearner Learner;	  
												/** list of GenCos */
	  public Hashtable<String, GenCo> genCoList = new Hashtable<String, GenCo>() ;
	  
// LSE
												/** Number of LSEs */
	  public int J=3;
	  											/** LSEs location at node  */
	  private int[] LSEAtNode;
	  											/** LSE's Data: {LSE ID, at Node, L(0), L(1),L(2),L(3),L(4), ...,L(23)} */
	  private double[][] LSEData;
	  											/** LSE's list */
	  private ArrayList LSEList;    
	  											/** LSE's load profile for each hour [Hour][LSE] */
	  private double[][] LoadProfile;
	  											/** Twenty-four hours */
	  private static final int Hours = 24;
	  											/** list of LSEs */
	  public Hashtable<String, LSE> lseList = new Hashtable<String, LSE>() ;
// ISO
	  											/** Local marginal price for each hour and node [Hour][Node] */
	  private double [][] LMP;
	  											/** Current day */  
	  public static int D;
	  public Hashtable<String, Object> reportedSupplyOffer = new Hashtable<String, Object>();
	  public Hashtable<String, Hashtable> electricityDemand = new Hashtable<String, Hashtable>();
	  
//C-O-N-S-T-R-U-C-T-O-R------------------------------------------------------------------------------------------------------------------------------  


	    public Market(long seed)
	        {
	        super(seed);
	        }
	//-----------------------------------------------------------------
	    
	    //public void start(long RandomSeed)
	    public void start()
	        {
	        super.start();
	  
	  
	  
	  
	  
	  
	  //   public Market(long seed)
   //     {
    //	  super(seed);
    //	  initialiseMarket();
     //   }
      
    //  private void initialiseMarket() 
   //   {
    	 // branchList  = new ArrayList();  
    	  
    	Initials.InitGenCo  initG = new Initials.InitGenCo(this);
      	Initials.InitLSE    initL = new Initials.InitLSE(this);
      	Initials.InitBranch initB = new Initials.InitBranch(this);
      	Initials.InitNode initN   = new Initials.InitNode(this);
      	ElGrid elgrid             = new ElGrid();
      	
      	
      	
      	//I = initG.getNGenCo();  			// Obtains number of GenCos
      	//J = initL.getNLSE();				// Obtains number of LSEs
      	//N = initB.getNBranch();			// Obtains number of Branches
      	//K = initN.getNNode();				// Obtains number of Nodes
      
      	
      //	GenCoMoney = new double[I];
      
//----GenCo------------------------------------------------             	       	
   //   for(int d=0; d<TotalDays; d++){
      	//d++;
		//Switch		 = false;
		//GenCoAtNode  = new int[I];
		//LearnerList  = new ArrayList();
      	//ADList		 = new ArrayList();
      	//GenCoList    = new ArrayList();
        //GenCoData    = new double[I][8];
      	//LearningData = new double[I][12];
      	//TSupplyOffer = new double[I][4];
      	//RSupplyOffer = new double[I][4];

        // 	GenCoData    = initG.getGenCoData();    // Obtains GenCos' data
        //	LearningData = initG.getLearningData(); // Obtains GenCos' learning data
      	
/* ********* Money update needs to be fixed***************************************
	
      	        if (d>0){		
             		  for (int i=0;i<I;i++){               			
          		  GenCoData[i][7]= getGenCoMoney()[i];
          		  }	
      	        }
***************************************************************************/        	
      	GenCo gen =null;
      	for(int i=0; i<I; i++){
      		int id = i+1;
      		
      		
      		 gen = genCoList.get("genco"+id);      //(genCoList, i, (int) System.currentTimeMillis(), this, d, Switch, I);  // Initiates a new GenCo      	     		 		
      		gen.Switch = false;     		     		
      		schedule.scheduleOnce(gen, 0);   
      		
      		//while(!schedule.scheduleComplete()){

      		//System.out.println("scheduleOnce is running");
      		
      	
      		
      		
      		//	schedule.AFTER_SIMULATION;
      		
      		//reportedSupplyOffer.put("genco"+id, gen.reportedSupplyOffer);     		
      		//elgrid.addGenCoAtNodeK(gen, gen.node);                		
      	}    
      	
  		//while(schedule.AFTER_SIMULATION >=  schedule.getTime() ){	
  		//	System.out.println("scheduleComplete is FALSE");
  			//	}
  		//else{
  		
  		//System.out.println("scheduleComplete is TRUE");
	    
      	
      	
      	
      	
      	
      	
//----- LSE-------------------------------------------------     
      	LSEAtNode   = new int[J];
      	LSEList     = new ArrayList();
      	LSEData     = new double[J][26];
      	LoadProfile = new double[Hours][J] ;
      	
        				    // Obtains LSEs' data
      	
      	for(int j=0; j<J; j++){
      		int id = j+1;
      		LSE lse = new LSE();      		
      		lse = lseList.get("lse"+id);      		
      		schedule.scheduleOnce(lse, 1);	
      		
      		electricityDemand.put("lse"+id, lse.electricityDemand);
      		
      		
      		elgrid.addLSEAtNodeK(lse, lse.node);                        	
      		}
      	
//----- ISO-------------------------------------------------     	
      	LMP = new double[Hours][K];
      //	Commitment = new double[Hours][I];
      		
      		for (int h=0; h<Hours; h++){ 
      //		count++;
      		//ISO iso = new ISO(reportedSupplyOffer, electricityDemand, branchList, nodeData, h, this);					// Initiates a new ISO
      		ISO iso = new ISO(h, this);
      		schedule.scheduleOnce(iso, 2);					// Schedules this ISO
      		}
         
//----- GenCo----------------------------------------------           
    //  	Switch = true;
      		        		 
	 		for(int i=0; i<I; i++){ 
	 			int id = i+1;
	 			gen = genCoList.get("genco"+id);      		
	 		//	gen.Switch = true;
	 		//	gen.day = D;

	 			//schedule.scheduleOnce(gen, 3); 
	 		}
	 	}
    	  
	    
	
    //  }
//-------------------------------------------------------------------------------------------------
    
      

  //    public void start()
  //      {
   // 	  super.start();
    	  
  //      }
    //-------M-A-I-N---------------------------------------------------------------------------------------
 /*     public static void main(String[] args){
          Market market = new Market(System.currentTimeMillis());       
          market.start();
          long steps = 0;
          //while(steps < 5000)
          
          for(int i=0; i<1; i++){
          	market.schedule.step(market);
          	steps = market.schedule.getSteps();
          }
          
          System.out.println("Done!!!");
          market.finish();
          System.exit(0);
      }
      */
//-------M-A-I-N---------------------------------------------------------------------------------------
     public static void main(String[] args){
          Market market = new Market(System.currentTimeMillis());       
         // market.start();
          long steps = 0;
          long jobsMax=1;
          int stepMax=1;
          for (int jobs=0; jobs<=jobsMax-1; jobs++)
  	    {
          	  market.start();
          	do
    		 	{
          		if (!market.schedule.step(market))
   			   {
   				   System.err.println("Error with the step function of the AWEM model");
   				   break;
   			   }
          		//end of step
          		GenCo gen =null;
          	  	for(int i=0; i<market.I; i++){
          	  		int id = i+1;		
          	  		 gen = market.genCoList.get("genco"+id); 
          	  		 //gen.Switch = true;
          	 		 gen.day = market.D;
          	 		 gen.submittedOffer();
          	  	} 
    		 	}while (market.schedule.getSteps() < stepMax-1);
          	
  	    }
                  
          System.out.println("Done!!!");
          market.finish();
          System.exit(0);
      }
  
//----- Set and Get methods------------------------------------------------------------------------   

    /** Adds LSEs to the list */   
    public void setLSEList(Object lselist)
    {
    	LSEList.add(lselist);   	
    }
//-------------------------------------------------------------------------------------------------    
   
    /** Sets LSE's load profile for every hour and every LSE */ 
    public void SubmitLoadProfile(double loadprofile, int h, int jj){
    	LoadProfile[h][jj] = loadprofile;
    } 
 //-------------------------------------------------------------------------------------------------    
    /** Returns hourly load profiles */   
    public double[][] getLoadProfile(){
    	return LoadProfile;
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Sets true supply offer for each GenCo */ 
    public void setTSupplyOffer(double[] tsupplyoffer, int g){
    	for (int i=0; i<4; i++){
    		TSupplyOffer[g][i] = tsupplyoffer[i]; 	
    	}
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Sets reported supply offer for each GenCo */
    public void setRSupplyOffer(double[] rsupplyoffer, int g){
    	for (int i=0; i<4; i++){
    		RSupplyOffer[g][i] = rsupplyoffer[i]; 	
    	}
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Returns reported supply offer */
    public double[][] getRSupplyOffer(){
    	return RSupplyOffer;
    }
    
//-------------------------------------------------------------------------------------------------    
   
    /** Returns true supply offer */
    public double[][] getTSupplyOffer(){
    	return TSupplyOffer;
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Adds action domains to the list */
    public void addAactionDomain(ArrayList adlist){    	
    	ADList.add(adlist);
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Sets Learner */
    public void setLearnerList(SimpleStatelessLearner learner){    	
    	LearnerList.add(learner);
    	System.out.println("Seted");
    }
//-------------------------------------------------------------------------------------------------    
   
    /** Adds GenCos to the list */
    public void addGenCo(Object genco){    	
    	GenCoList.add(genco);
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Returns GenCos' list */
    public ArrayList getGenCo(){    	
    	return GenCoList;
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Sets LMP list for each hour and node */
    public void setLMPList(double[] lmp, int h ){    	 	
    	for (int i=0; i<K; i++){
    		LMP[h][i] = lmp[i];
    	}
    }
//-------------------------------------------------------------------------------------------------    
    
  //  /** Sets boolean Switch */
 //   public void setSwitch(boolean sw){    	
 //   	Switch = sw;
 //   }
//-------------------------------------------------------------------------------------------------    
    
 //   /** Returns boolean Switch */
  //  public boolean getSwitch(){
  //  	return Switch;
  //  }
//-------------------------------------------------------------------------------------------------    
    /** Sets hourly power production quantity for each GenCo */
   // public void setCommitment(double[] commitment, int h ){   	 
   // 	for (int i=0; i<I; i++){
   // 		Commitment[h][i] = commitment[i];
   // 	}
   // }
//-------------------------------------------------------------------------------------------------    
 //   /** Returns hourly power production quantity by GenCos  */
 //   public double[][] getCommitment(){
 //   	return Commitment;	
 //   }
//-------------------------------------------------------------------------------------------------    
    
    /** Returns LMP */
    public double[][] getLMP(){
    	return LMP;	
    }
//-------------------------------------------------------------------------------------------------    
 
    /** Sets accumulative money holding for each GenCo*/
	public void setGenCoMoney(int i, double gencomoney){
		GenCoMoney[i] = GenCoMoney[i]+gencomoney;		
		//if (i==0){
		//System.out.println(GenCoMoney[i]);}
		//System.out.println("i= "+i+" "+GenCoMoney[i]+"   "+gencomoney[i]);
	}
//-------------------------------------------------------------------------------------------------    

	/** Returns GenCo's accumulative money holding*/
	public double[] getGenCoMoney(){		
		return GenCoMoney;
	}
//-------------------------------------------------------------------------------------------------    

	
	
	
	
	
}
